﻿using System;
using System.Collections.Generic;
using System.Text;
using ITAP.ShprossesBuilder.Modelling.Components;
using ITAP.ShprossesBuilder.Calculations;
using ITAP.ShprossesBuilder.Modelling;
using System.Drawing;
using System.Windows.Forms;
using ITAP.Core.Modelling;
using ITAP.Core.Calculations;

namespace ITAP.ShprossesBuilder.Manipulation
{
    public class CommandEditorNavigation : IModelComponentCommand
    {        
        private List<Type> ignoredTypes;
        private bool executeImmediately = false;
        private string name;
        ModelPoint startCameraPoint;
        Point mouseDownPoint;
        Point mouseMovePoint;
        Point mouseUpPoint;
        private MouseManagerEvent mouseEvent;

        public MouseManagerEvent MouseEvent
        {
            get { return mouseEvent; }
            set { mouseEvent = value; }
        }
                                       
        private ModelControl modelControl;

        public CommandEditorNavigation(ModelControl modelControl, Type[] ignoredTypes, string name)
        {
            this.ignoredTypes = new List<Type>(ignoredTypes);
            this.name = name;
            this.modelControl = modelControl;
        //    startCameraPoint = (ModelPoint)modelControl.Camera.Clone();

        }

        #region IModelControlCommand Members

        public ModelControl ModelControl
        {
            get
            {
                return modelControl;
            }
            set
            {
                modelControl = value;
            }
        }

        public Point MouseDownPoint
        {
            get
            {
                return mouseDownPoint;
            }
            set
            {
                mouseDownPoint = value;
            }
        }

        public Point MouseUpPoint
        {
            get
            {
                return mouseUpPoint;
            }
            set
            {
                mouseUpPoint = value;
            }
        }

        public Point MouseMovePoint
        {
            get
            {
                return mouseMovePoint;
            }
            set
            {
                mouseMovePoint = value;
            }
        }

        #endregion

        #region ICommand Members

        public void StartExecute()
        {
            if (modelControl.Camera == null)
                return;

            ModelPoint modelPoint = modelControl.ScreenToModel(mouseDownPoint);
            List<IComponent> components = modelControl.ModelContainer.GetComponentsByPoint(modelPoint, 10);
            
            foreach(IComponent component in components)
                if(!ignoredTypes.Contains(component.GetType()))
                    return;

            startCameraPoint = (ModelPoint)modelControl.Camera.Clone();
            mouseMovePoint = mouseDownPoint;
            enabled = true;
        }

        public void Execute()
        {
            if (enabled)
            {
                this.Move();
            }
        }

        public void EndExecute()
        {
            if (enabled)
            {
                this.Move();
                enabled = false;
            }
        }

        private void Move()
        {
            Point offsetPoint = new Point(mouseMovePoint.X - mouseDownPoint.X, mouseMovePoint.Y - mouseDownPoint.Y);
            RectangleF bbox = modelControl.ModelContainer.BoundingBox;
            double modelXOffset = modelControl.CoordinateConverter.ScreenMeasureToModelMeasure(offsetPoint.X, modelControl.ClientRectangle.Width, modelControl.ClientRectangle.Height, bbox);
            double modelYOffset = modelControl.CoordinateConverter.ScreenMeasureToModelMeasure(offsetPoint.Y, modelControl.ClientRectangle.Width, modelControl.ClientRectangle.Height, bbox);
            ModelVector vector = new ModelVector(-modelXOffset, modelYOffset);
            modelControl.Camera = ModelCalculations.GetOffsetPoint(startCameraPoint, vector);
        }

        public bool CanUndo
        {
            get { return false; }
        }

        public bool Undo(ModelControl modelControl)
        {
            throw new NotImplementedException();
        }

        public bool Redo(ModelControl modelControl)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region ICloneable Members

        public object Clone()
        {
            CommandEditorNavigation clone = new CommandEditorNavigation(modelControl, ignoredTypes.ToArray(), name);
            clone.MouseEvent = this.MouseEvent;
            clone.MouseDownPoint = this.MouseDownPoint;
            clone.MouseMovePoint = this.MouseMovePoint;
            clone.MouseUpPoint = this.MouseUpPoint;
            if(this.startCameraPoint != null)
                clone.startCameraPoint = (ModelPoint)this.startCameraPoint.Clone();
            clone.ExecuteImmediately = this.ExecuteImmediately;
            if(this.ComponentsForProcessing != null)
                clone.ComponentsForProcessing = new List<IComponent>(this.ComponentsForProcessing);
            return clone;
        }

        #endregion

        #region ICommand Members

        public string Name
        {
            get { return name; }
        }

        #endregion

        #region IModelControlCommand Members


        public bool ExecuteImmediately
        {
            get
            {
                return executeImmediately;
            }
            set
            {
                executeImmediately = value;
            }
        }

        #endregion

        #region IModelComponentCommand Members

        public List<IComponent> ComponentsForProcessing
        {
            get
            {
                return null;
            }
            set
            {
            }
        }

        #endregion

        #region ICommand Members


        public bool IsNeedModelUpdate
        {
            get { return false; }
        }

        #endregion

        #region ICommand Members



        private bool enabled = false;

        private bool _enabled = true;
        public bool Enabled
        {
            get
            {
                return _enabled;
            }
            set
            {
                _enabled = value;
            }
        }
        #endregion

        #region ICommand Members


        public bool IsNeedVisitorsUpdate
        {
            get { return true; }
        }

        #endregion
    }
}
